/*
 * MAX7456 osd high level functions library
 *
 * Written by Florian MAZEN and Pierre COL, 2008-2009
 * <euronym AT free.fr>
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public License
 * as published by the Free Software Foundation; either version 3
 * of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 */
#include "max7456.h"
#include "osd.h"

/* Set the current character adress */
void osd_locate_absolute(unsigned int pos)
{
	unsigned int posH;
	posH = pos >> 8;
	posH &= 0x01;
	max7456_write_register(MAX7456_DMAL_W, (unsigned char) pos);
	max7456_write_register(MAX7456_DMAH_W, (unsigned char) posH);
}
void osd_locate(unsigned char x, unsigned char y)
{
	unsigned int pos;
	pos = y * 30;
	pos += x;
	max7456_write_register(MAX7456_DMAL_W, (unsigned char) pos);
	pos = pos >> 8;
	pos &= 0x01;
	max7456_write_register(MAX7456_DMAH_W, (unsigned char) pos);
}

/* Reset OSD device */
void osd_reset(void)
{
	max7456_write_register(MAX7456_VM0_W, 0x02);
	delayMicroseconds(150); //150µs
	while( (max7456_read_register(MAX7456_VM0_W) & 0x02) == 0x02); // Wait reset finished
}

/* Clear display*/
void osd_cls(void)
{
	int i;
	unsigned char osd_DMM;
	// Set locate 0
	max7456_write_register(MAX7456_DMAL_W, 0);
	max7456_write_register(MAX7456_DMAH_W, 0);

	/* Set OSD auto increment mode */
	osd_DMM = max7456_read_register(MAX7456_DMM_R);
	osd_DMM &= 0xfd;
	osd_DMM |= 0x01;
	max7456_write_register(MAX7456_DMM_W, osd_DMM);
	// Clear
	for (i = 0; i < 480; i++)
		max7456_write_autoincrement_byte(0);
	// End auto increment mode
	max7456_write_autoincrement_byte(MAX7456_END_AUTO_INCREMENT);
}

/* Display a new character */
void osd_putchar(unsigned char c) 
{
	unsigned char pos;
	max7456_write_register(MAX7456_DMDI_W, max7456_ascii2osdChars(c));
	pos = max7456_read_register(MAX7456_DMAL_R);
	pos++;
	max7456_write_register(MAX7456_DMAL_W, pos);
}

/* Turn on or off osd display */
void osd_enable(void)
{
	unsigned char vm0;
	vm0 = max7456_read_register(MAX7456_VM0_R);
	vm0 |= 0x08;
	max7456_write_register(MAX7456_VM0_W, vm0);
}

void osd_disable(void)
{
	unsigned char vm0;
	vm0 = max7456_read_register(MAX7456_VM0_R);
	vm0 &= 0x07;
	max7456_write_register(MAX7456_VM0_W, vm0);
}

/* Set video standard (PAL, NTSC) and OSD sync mode (Auto, internal, external) */
void osd_setVideoMode(unsigned char standard, unsigned char sync)
{
	unsigned char vm0;
	vm0 = max7456_read_register(MAX7456_VM0_R);
	if (standard == OSD_PAL)
		vm0 |= 0x40;
	else
		vm0 &= 0xbf;
	vm0 &= 0xcf;
	if (sync == OSD_SYNC_INT)
	{
		vm0 |= 0x30;
	}
	else if (sync == OSD_SYNC_EXT)
	{
		vm0 |= 0x20;
	}
	max7456_write_register(MAX7456_VM0_W, vm0);
}

/* Set attribute */
void osd_setCharactersAttribute(unsigned char att) 
{
	unsigned char dmm;
	dmm = max7456_read_register(MAX7456_DMM_R) & 0xc7;
	dmm = dmm | ((att & 0x07) << 3);
	max7456_write_register(MAX7456_DMM_W, dmm);
}
/* Get attribute */
unsigned char osd_getCharactersAttribute(void)
{
	return (max7456_read_register(MAX7456_DMM_R) & 0xc7) >> 3;
}

/* Get the current level of gray of the background */
unsigned char osd_getBackgroundBrightness(void)
{
	return (max7456_read_register(MAX7456_VM1_R) & 0x70) >> 4;
}
/* Set the level of gray of the background 
  Values can be 0. to 7 */
void osd_setBackgroundBrightness(unsigned char level) 
{
	unsigned char vm1;
	vm1 = max7456_read_register(MAX7456_VM1_R) & 0x8f;
	vm1 = vm1 & ((level & 7) << 4);
	max7456_write_register(MAX7456_VM1_W, vm1);
}

/* Set blinking time parameter (BT) 
	blinkingTime duration from 0 to 3
  Check constants for values
*/
void osd_setBlinkingTime(unsigned char blinkingTime) 
{
	unsigned char vm1;
	vm1 = max7456_read_register(MAX7456_VM1_R) & 0xf3;
	vm1 = vm1 & ((blinkingTime & 3) << 2);
	max7456_write_register(MAX7456_VM1_W, vm1);
}

/* Get blinking time parameter (BT) */
unsigned char osd_getBlinkingTime(void)
{
	return (max7456_read_register(MAX7456_VM1_R) & 0x0c) >> 2;
}

/* Set blinking time parameter
        blinkingTime duty cycle from 0 to 3
  Check constants for values
*/
void osd_setBlinkingDutyCycle(unsigned char blinkingDuty) 
{
	unsigned char vm1;
	vm1 = max7456_read_register(MAX7456_VM1_R) & 0xfc;
	vm1 = vm1 & (blinkingDuty & 3);
	max7456_write_register(MAX7456_VM1_W, vm1);
}

/* Get blinking time parameter */
inline unsigned char osd_getBlinkingDutyCycle(void)
{
	return max7456_read_register(MAX7456_VM1_R) & 0x03;
}

/* Set Horizontal Offset */
inline void osd_setHOS(unsigned char val)
{
	max7456_write_register(MAX7456_HOS_W, val);
}
/* Set Horizontal Offset */
inline unsigned char osd_getHOS(void)
{
	return max7456_read_register(MAX7456_HOS_R);
}

/* Set Vertical Offset */
inline void osd_setVOS(unsigned char val)
{
	max7456_write_register(MAX7456_VOS_W, val);
}
/* Set Vertical Offset */
inline unsigned char osd_getVOS(void)
{
	return max7456_read_register(MAX7456_VOS_R);
}
